package com.chushouya.common.support;

import com.chushouya.common.dto.QueueMessage;
import com.general.framework.core.lang.Jsons;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * 消息监听器基类
 * 提供消息处理的通用逻辑
 * 
 * @author chushouya team
 */
@Slf4j
public abstract class BaseMessageListener {

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 处理消息的抽象方法，子类需要实现
     * 
     * @param queueMessage 队列消息
     * @return 是否处理成功
     */
    protected abstract boolean processMessage(QueueMessage<?> queueMessage);

    /**
     * 消息处理入口
     * 
     * @param message 原始消息
     * @param channel 通道
     * @param deliveryTag 投递标签
     */
    protected void handleMessage(Message message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        QueueMessage<?> queueMessage = null;
        try {
            // 解析消息
            String messageBody = new String(message.getBody());
            queueMessage = Jsons.parseObject(messageBody, QueueMessage.class);
//
            log.info("接收到消息 - ID: {}, 类型: {}, 重试次数: {}",
                    queueMessage.getMessageId(),
                    queueMessage.getMessageType(),
                    queueMessage.getRetryCount());

            // 处理消息
//            boolean success = processMessage(queueMessage);
            
//            if (success) {
//                // 处理成功，确认消息
//                channel.basicAck(deliveryTag, false);
//                log.info("消息处理成功 - ID: {}", queueMessage.getMessageId());
//            } else {
//                // 处理失败，判断是否需要重试
//                handleProcessFailure(queueMessage, channel, deliveryTag);
//            }
            
        } catch (Exception e) {
//            log.error("消息处理异常 - ID: {}, 错误: {}",
//                    queueMessage != null ? queueMessage.getMessageId() : "unknown",
//                    e.getMessage(), e);
//
//            try {
//                if (queueMessage != null) {
//                    handleProcessFailure(queueMessage, channel, deliveryTag);
//                } else {
//                    // 消息解析失败，直接拒绝
//                    channel.basicNack(deliveryTag, false, false);
//                }
//            } catch (IOException ioException) {
//                log.error("消息确认失败", ioException);
//            }
        }
    }

    /**
     * 处理消息处理失败的情况
     * 
     * @param queueMessage 队列消息
     * @param channel 通道
     * @param deliveryTag 投递标签
     * @throws IOException IO异常
     */
    private void handleProcessFailure(QueueMessage<?> queueMessage, Channel channel, long deliveryTag) throws IOException {
        queueMessage.incrementRetryCount();
        
        if (queueMessage.isExceedMaxRetry()) {
            // 超过最大重试次数，拒绝消息并不重新入队
            channel.basicNack(deliveryTag, false, false);
            log.warn("消息处理失败且超过最大重试次数 - ID: {}, 重试次数: {}", 
                    queueMessage.getMessageId(), queueMessage.getRetryCount());
            
            // 可以在这里实现死信队列逻辑或者其他处理
            handleDeadLetter(queueMessage);
        } else {
            // 未超过最大重试次数，拒绝消息并重新入队
            channel.basicNack(deliveryTag, false, true);
            log.warn("消息处理失败，将重新入队 - ID: {}, 重试次数: {}", 
                    queueMessage.getMessageId(), queueMessage.getRetryCount());
        }
    }

    /**
     * 处理死信消息，子类可以重写此方法
     * 
     * @param queueMessage 死信消息
     */
    protected void handleDeadLetter(QueueMessage<?> queueMessage) {
        log.error("消息进入死信队列 - ID: {}, 类型: {}", 
                queueMessage.getMessageId(), queueMessage.getMessageType());
        // 子类可以重写此方法，实现自定义的死信处理逻辑
        // 比如：记录到数据库、发送告警等
    }

    /**
     * 获取消息类型，用于消息路由
     * 
     * @param queueMessage 队列消息
     * @return 消息类型
     */
    protected String getMessageType(QueueMessage<?> queueMessage) {
        return queueMessage.getMessageType();
    }

    /**
     * 获取消息数据
     * 
     * @param queueMessage 队列消息
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的数据
     */
    protected <T> T getMessageData(QueueMessage<?> queueMessage, Class<T> clazz) {
        try {
            Object data = queueMessage.getData();
            if (data == null) {
                return null;
            }
            
            if (clazz.isInstance(data)) {
                return clazz.cast(data);
            }
            
            // 使用ObjectMapper进行类型转换
            return objectMapper.convertValue(data, clazz);
        } catch (Exception e) {
            log.error("消息数据转换失败 - 目标类型: {}, 错误: {}", clazz.getSimpleName(), e.getMessage(), e);
            return null;
        }
    }
}
